package socket;

import FCRendering.FCRMaster;
import Function.FCMutilPlayCache;
import Function.FCMutilPlayPropulsionCache;
import Function.FCMutilPlaySender;
import Function.FCMutilPlayTankCache;
import VWorldGameStudio.*;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.reactivex.schedulers.Schedulers;
import socket.protocol.IProtocolServer;
import socket.protocol.ProtocolServerType1;
import socket.util.ByteUtil;
import socket.util.SLog;
import utils.FCMixUtil;
import utils.entity.BigTankPack;
import utils.entity.MsgPack;
import utils.entity.RandomPack;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;

import static FCRendering.FCRMaster.*;

public class FCRSocketServer implements IProtocolServer.OnNeedCallback {
    interface Work {
        void doWhat(FCMutilPlaySender sender);
    }

    private static FCRSocketServer socketServer;
    Gson gson = new Gson();
    private Object tankLock = new Object();
    static {
        socketServer = new FCRSocketServer();
    }

    public static FCRSocketServer getIn() {
        return socketServer;
    }

    private ProtocolServerType1 protocolServer;

    //key 是socketKey， val 是 FCMutilPlaySender
    ConcurrentHashMap<String, FCMutilPlaySender> senderHelpMaps = new ConcurrentHashMap<>();
    //key 是host， val 是socketKey
    ConcurrentHashMap<String, String> hostIdAndSocketKeyMap = new ConcurrentHashMap<>();

    private FCRSocketServer() {

    }

    public void initServer() {
        if (protocolServer == null) {
            SLog.getInstance().initLogFile("", null);
            protocolServer = new ProtocolServerType1(this);
            protocolServer.connect(2, 5500);
        }
    }

    @Override
    public void onConnectedStatusChanged(String key, boolean connected, Exception e, String msg) {
        if (!connected) {
            //断开连接时，就把记录的不同UID的移除咯
            String hostId = null;
            Iterator<Map.Entry<String, String>> iterator = hostIdAndSocketKeyMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> m = iterator.next();
                if (key.equals(m.getValue())) {
                    hostId = m.getKey();
                    break;
                }
            }
            if (hostId != null) {
                senderHelpMaps.remove(key);
                hostIdAndSocketKeyMap.remove(hostId);
                /**
                 * TODO 还要广播出去通知这个人退出了，
                 */
                FCMutilPlayCache.aPlayerExitGame(hostId);
                final String finalHostId = hostId;
                eachSenderDo(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.sendNotifyAPlayerExitGame(finalHostId);
                    }
                });
                SLog.getInstance().e_s("玩家 " + hostId + " 退出了");
            }
        } else {
            if (!senderHelpMaps.containsKey(key)) {
                FCMutilPlaySender fcMutilPlaySender = new FCMutilPlaySender(key, protocolServer);
                senderHelpMaps.put(key, fcMutilPlaySender);
            }
        }
    }

    private void eachSenderDoExcept(Work work, String except) {
        Iterator<Map.Entry<String, FCMutilPlaySender>> iterator = senderHelpMaps.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, FCMutilPlaySender> entry = iterator.next();
            if (!entry.getKey().equals(except)) {
                Schedulers.computation().scheduleDirect(new Runnable() {
                    @Override
                    public void run() {
                        work.doWhat(entry.getValue());
                    }
                });
            }
        }
    }

    private void eachSenderDoInTeam(Work work) {
        ArrayList<String> teamHost = new ArrayList<>();
        for (FCRPlayerLink link : FCMutilPlayCache.getTeamMembers()) {
            if (!link.curPlayerHostUID.equals("npc") && !link.curPlayerHostUID.equals(gameSave.HOST_UID)) {
                if (!teamHost.contains(link.curPlayerHostUID)) {
                    teamHost.add(link.curPlayerHostUID);
                }
            }
        }
        for (String host : teamHost) {
            Schedulers.computation().scheduleDirect(new Runnable() {
                @Override
                public void run() {
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(host));
                    if (sender != null) {
                        work.doWhat(sender);
                    }
                }
            });
        }
    }

    private void eachSenderDo(Work work) {
        Iterator<Map.Entry<String, FCMutilPlaySender>> iterator = senderHelpMaps.entrySet().iterator();
        while (iterator.hasNext()) {
            work.doWhat(iterator.next().getValue());
        }
    }

    //公共行为，只对服务器
    private void sendPlayer(String key) {
        if (protocolServer == null) {
            return;
        }
        FCMutilPlaySender sender = senderHelpMaps.get(key);
        if (sender != null) {
            sender.sendAllPlayerAndTeam(FCRSocketConstant.S2C_SEND_RES_PLAYER);
        }
    }

    //公共行为，服务端要请求同步出去
    public void sendTanksSync() {
        if (protocolServer == null) {
            return;
        }
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.sendTanksSync();
            }
        });
    }


    //申请加入
    public void requestJoinYou() {
        if (protocolServer == null) {
            return;
        }
        if (fcv.isInTeamLink()) {
            //TODO 在别人的队伍中不能操作
            return;
        }
        FCPlayerInfo playerInfo = FCMutilPlayCache.findPlayerByHostId(fcv.getCurTeamMenuClickPlayerHost());
        if (playerInfo != null) {
            if (!playerInfo.getMapname().equals(player1.getMapname())) {
                fcv.getMessage().add("申请组队玩家必须同一地图！");
                fcv.showMessage();
                return;
            }
        } else {
            fcv.getMessage().add("玩家不存在了");
            fcv.showMessage();
            return;
        }
        //TODO 要是自己是队长，不能连续组2个联机玩家
        boolean hasOtherPlayer = false;
        for (FCRPlayerLink link : FCMutilPlayCache.getTeamMembers()) {
            if (!link.curPlayerHostUID.equals(gameSave.HOST_UID)) {
                hasOtherPlayer = true;
                break;
            }
        }
        if (!hasOtherPlayer) {
            FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(fcv.getCurTeamMenuClickPlayerHost()));
            if (sender != null) {
                sender.sendRequestJoinYou();
            }
        } else {
            fcv.getMessage().add("不可以连续组更多的玩家了!");
            fcv.showMessage();
        }
    }

    //邀请组队
    public void requestJoinMe() {
        if (protocolServer == null) {
            return;
        }
        if (fcv.isInTeamLink()) {
            //TODO 在别人的队伍中不能操作
            return;
        }
        if (fcv.isInTeamLink()) {
            //TODO 在别人的队伍中不能操作
            fcv.getMessage().add("你已经在一个队伍里了");
            fcv.showMessage();
            return;
        }
        //TODO 需要对方在同一个地图，不让不能组队
        FCPlayerInfo playerInfo = FCMutilPlayCache.findPlayerByHostId(fcv.getCurTeamMenuClickPlayerHost());
        if (playerInfo != null) {
            if (!playerInfo.getMapname().equals(player1.getMapname())) {
                fcv.getMessage().add("申请组队玩家必须同一地图！");
                fcv.showMessage();
                return;
            }
        } else {
            fcv.getMessage().add("玩家不存在了");
            fcv.showMessage();
            return;
        }

        //TODO 要是自己是队长，不能连续组2个联机玩家
        boolean hasOtherPlayer = false;
        for (FCRPlayerLink link : FCMutilPlayCache.getTeamMembers()) {
            if (!link.curPlayerHostUID.equals(gameSave.HOST_UID)) {
                hasOtherPlayer = true;
                break;
            }
        }
        if (!hasOtherPlayer) {
            FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(fcv.getCurTeamMenuClickPlayerHost()));
            if (sender != null) {
                sender.sendRequestJoinMe();
            }
        } else {
            fcv.getMessage().add("不可以连续组更多的玩家了!");
            fcv.showMessage();
        }
    }


    public void repoRequestJoin(boolean yesOrNo) {
        if (protocolServer == null) {
            return;
        }
        if (fcv.getTeamReqeuestFromWho() != null) {
            FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(fcv.getTeamReqeuestFromWho()));
            if (sender != null) {
                sender.sendRepoRequestJoin(yesOrNo);
            }
        }
    }

    /**
     * 人物有移动就发,公共行为的
     */
    public void playerMoving() {

        if (protocolServer == null)
            return;
        if (fcv.isInTeamLink()) {
            //TODO 在别人的队伍中不能发送位置了
            return;
        }

        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                Schedulers.computation().scheduleDirect(new Runnable() {
                    @Override
                    public void run() {
                        sender.sendMoving(FCRSocketConstant.S2C_SEND_MOVING);
                    }
                });
            }
        });
    }

    public void playerJoinIn() {
        if (protocolServer == null) {
            return;
        }
        if (fcv.getCurTeamMenuClickPlayerHost() != null) {
            FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(fcv.getCurTeamMenuClickPlayerHost()));
            if (sender != null) {
                sender.sendRequestJoinIn(gameSave.HOST_UID, fcv.getCurTeamMenuClickPlayerHost());
            }
        } else {
            FCRMaster.fcv.getMessage().add("没有选择玩家");
            fcv.showMessage();
        }
    }

    public void playerJoinOut() {
        if (protocolServer == null) {
            return;
        }
        sendQuitTeam();
    }

    /**
     * 注意了哈，这里不管是队员还是队长都能主动退出队伍 叫对方退出加标志
     */
    private void sendQuitTeam() {
        if (fcv.isInTeamLink()) {
            //就是在别人的队咯，要通知对方把你移除队伍里
            fcv.setInTeamLink(false);
            //TODO 如果有牵引物，就要重整一下
            FCRMaster.player1.resetPropulsionIfNeed();
            //只要给队长发退出就行了
            if (fcv.getTeamLeader() != null) {
                String formToData = gameSave.HOST_UID + "@" + fcv.getTeamLeader();
                byte[] formToDatab = formToData.getBytes();
                byte[] data = new byte[1 + formToDatab.length];
                data[0] = 1;
                System.arraycopy(formToDatab, 0, data, 1, formToDatab.length);
                //TODO 不管怎样都要发一条给人家，
                FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(fcv.getTeamLeader()));
                if (fcMutilPlaySender != null) {
                    fcMutilPlaySender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_OUT, data);
                }
                fcv.setTeamLeader(null);
            }
        } else {
            ArrayList<String> hostIdNeedSend = new ArrayList<>();
            for (FCRPlayerLink link : FCMutilPlayCache.getTeamMembers()) {
                if (!link.curPlayerHostUID.equals(gameSave.HOST_UID) && !hostIdNeedSend.contains(link.curPlayerHostUID)) {
                    hostIdNeedSend.add(link.curPlayerHostUID);
                }
            }

            //就是解散整个队伍了，全部人都发
            for (String hostId : hostIdNeedSend) {
                //自己是队长,把非自己的UID的队员全踢了,通知对方把自己的标记设置
                FCMutilPlayCache.removeOtherInTeamNetPlayers(hostId);
                //TODO 移除掉别的玩家的牵引物
                FCRMaster.player1.removeRemotePropulsion(hostId);
                FCRMaster.player1.resetPropulsionIfNeed();
                String formToData = gameSave.HOST_UID + "@" + hostId;
                byte[] formToDatab = formToData.getBytes();
                byte[] data = new byte[1 + formToDatab.length];
                data[0] = 0;
                System.arraycopy(formToDatab, 0, data, 1, formToDatab.length);
                //TODO 不管怎样都要发一条给人家，
                FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(hostId));
                if (fcMutilPlaySender != null) {
                    fcMutilPlaySender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_OUT, data);
                }
            }
        }
    }

    //表示再同步一次人物属性
    public void reCreatePlayerAgian() {
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sendPlayer(sender.getSocketKey());
            }
        });
    }

    public void sendPlayerUpDownTank(FCPlayerInfo p) {
        if (protocolServer == null) {
            return;
        }
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.sendPlayerUpDownTank(p);
            }
        });
    }

    //队伍接口
    public void playerJumpEvent(String fcEventName, String destMapName) {
        if (protocolServer == null) {
            return;
        }
        if (fcv.isInTeamLink()) {
            //TODO 在别人的队伍中不能操作
            return;
        }
        //TODO 对方不在你队伍你也不能发
        eachSenderDoInTeam(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.sendFCJumpEvent(fcEventName, destMapName);
            }
        });
    }


    //队伍接口
    public void battelReady(FCPlayerBattleWrap s) {
        if (protocolServer == null) {
            return;
        }
        ArrayList<String> teamHost = new ArrayList<>();
        for (FCPlayerBattleWrap wrap : fcv.getBattleWraps()) {
            if (!wrap.getHostUid().equals("npc") && !wrap.getHostUid().equals(gameSave.HOST_UID)) {
                if (!teamHost.contains(wrap.getHostUid())) {
                    teamHost.add(wrap.getHostUid());
                }
            }
        }
        for (String targetHost : teamHost) {
            FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(targetHost));
            if (fcMutilPlaySender != null) {
                fcMutilPlaySender.sendPlayerBattleReady(s);
            }
        }
    }

    //队伍接口
    public void syncJumpToBattle() {
        if (protocolServer == null) {
            return;
        }

        //STEP2 优先同步下坦克先
        sendTanksSync();

        eachSenderDoInTeam(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.sendBattleStart();
            }
        });
    }

    //同步组队场景变化
    public void syncMultiPlayScreen() {
        if (protocolServer == null) {
            return;
        }
        FCMultiSyncScreenPack teamScreenPack = new FCMultiSyncScreenPack();
        teamScreenPack.doorX = fcrMaster.getOpendoorx();
        teamScreenPack.doorY = fcrMaster.getOpendoory();
        teamScreenPack.isOpenDoor = fcrMaster.isIsplayopendoormusic();
        teamScreenPack.mapName = player1.getMapname();
        teamScreenPack.srcHostId = gameSave.HOST_UID;
        ;
        String data = gson.toJson(teamScreenPack);
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.throughTransmissionSend(FCRSocketConstant.COMMON_TEAM_SCREEN_SYNC, data.getBytes());
            }
        });
    }

    public void syncBattleRandoms(ArrayList<Float> floats){
        if (protocolServer == null || floats.size() == 0) {
            return;
        }
        RandomPack randomPack = new RandomPack();
        randomPack.floatArrayList = floats;
        String data = gson.toJson(randomPack);
        eachSenderDoInTeam(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.throughTransmissionSend(FCRSocketConstant.COMMON_BATTLE_RANDOMS, data.getBytes());
            }
        });
    }

    public void syncPlayerEquip(FCPlayerInfo p) {
        if (protocolServer == null) {
            return;
        }
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.sendPlayerSyncEquip(p);
            }
        });
    }

    //直接改变对方玩家的角色属性比如血量，状态移除等,这个是非战斗情况下用的
    public void syncPlayerState(List<FCPlayerInfo> targetP) {
        if (protocolServer == null) {
            return;
        }
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                Schedulers.computation().scheduleDirect(new Runnable() {
                    @Override
                    public void run() {
                        sender.syncOnePlayerState(targetP);
                    }
                });
            }
        });
    }

    //同步服务器的共显对象给其他客机
    public void syncFCPropulsion(FCPropulsion fcPropulsion) {
        if (protocolServer == null) {
            return;
        }
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                sender.sendFCPropulsion(fcPropulsion);
            }
        });
    }


    //同步所有服务器的共显对象给其他客机
    private void syncAllFCPropulsionToClient() {
        if (protocolServer == null) {
            return;
        }
        eachSenderDo(new Work() {
            @Override
            public void doWhat(FCMutilPlaySender sender) {
                Schedulers.computation().scheduleDirect(new Runnable() {
                    @Override
                    public void run() {
                        sender.sendAllFCPropulsion();
                    }
                });
            }
        });
    }

    public void sendBrocastPlayerMsg(String msg){
        if(msg == null){
            player1.setTalkingMsg(null);
            return;
        }
        System.out.println("sendBrocastPlayerMsg "+msg);
        if(msg.length() == 0){
            player1.setTalkingMsg(null);
            return;
        }
        if("请输入对话".equals(msg)){
            player1.setTalkingMsg(null);
            return;
        }
        if(msg.equals(player1.getTalkingMsg())){
            return;
        }
        if(msg.length() > 20){
            msg = msg.substring(0,20);
        }
        player1.setTalkingMsg(msg);
        if (protocolServer == null) {
            return;
        }
        MsgPack pack = new MsgPack();
        pack.msg = msg;
        pack.playerName = player1.getName();
        pack.hostId = gameSave.HOST_UID;
        String s = gson.toJson(pack);
        byte[] sendData = s.getBytes();
        if (sendData.length > 0) {
            eachSenderDo(new Work() {
                @Override
                public void doWhat(FCMutilPlaySender sender) {
                    Schedulers.computation().scheduleDirect(new Runnable() {
                        @Override
                        public void run() {
                            sender.throughTransmissionSend(FCRSocketConstant.COMMON_PLAYER_TALK_MSG,sendData);
                        }
                    });
                }
            });
        }
    }

    /**
     * 驾驶操作别的玩家的坦克的区域
     **/
    public void getYouTankItemsToMe(String tankId, String tankHostId) {
        if (protocolServer == null) {
            return;
        }
        String s = tankHostId + "," + tankId + "," + gameSave.HOST_UID;
        FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(tankHostId));
        if (fcMutilPlaySender != null) {
            fcMutilPlaySender.throughTransmissionSend(FCRSocketConstant.COMMON_GIVE_ME_YOUR_TANKITEMS, s.getBytes());
        }

    }

    //上下你的车
    public void upOrDownYouTank(String tankId, String tankHostId, boolean isUp) {
        if (protocolServer == null) {
            return;
        }
        String s = tankHostId + "," + tankId + "," + (isUp ? 1 : 0);
        FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(tankHostId));
        if (fcMutilPlaySender != null) {
            fcMutilPlaySender.throughTransmissionSend(FCRSocketConstant.COMMON_UP_DOWN_YOUR_TANK, s.getBytes());
        }
    }

    //行走后同步
    public void syncYouTankMoving() {
        if (protocolServer == null) {
            return;
        }
        HashMap<String, ArrayList<FCTank>> filters = new HashMap<>();
        //STEP 1判断队伍里是不是有其他玩家的车
        FCPlayerInfo checkPlayer = player1;

        for (int i = -1; i < FCMutilPlayCache.getTeamMembers().size(); i++) {
            if (i == -1) {

            } else {
                FCRPlayerLink link = FCMutilPlayCache.getTeamMembers().get(i);
                checkPlayer = FCMutilPlayCache.findPlayerByName(link.curPlayerHostUID, link.curPlayerName);
            }
            if (checkPlayer != null && checkPlayer.getAliasUID().equals(gameSave.HOST_UID)) {
                if (checkPlayer.getPlayertank1() != null && !checkPlayer.getPlayertank1().equals("null") && !checkPlayer.getPlayertankHostId().equals(gameSave.HOST_UID)) {
                    FCTank fcTank = tankLib.getTankOfID(checkPlayer.getPlayertank1(), checkPlayer.getPlayertankHostId());
                    if (fcTank != null) {
                        ArrayList<FCTank> ls = filters.get(checkPlayer.getPlayertankHostId());
                        if (ls == null) {
                            ls = new ArrayList<>();
                            filters.put(checkPlayer.getPlayertankHostId(), ls);
                        }
                        ls.add(fcTank);
                        FCMutilPlayPropulsionCache.shareIt(fcTank);
                    }
                }
            }
        }
        if (filters.size() > 0) {
            filters.forEach(new BiConsumer<String, ArrayList<FCTank>>() {
                @Override
                public void accept(String s, ArrayList<FCTank> fcTanks) {
                    ArrayList<String> datas = new ArrayList<>(fcTanks.size());
                    for (FCTank fcTank : fcTanks) {
                        datas.add(fcTank.getHostId() + "," + fcTank.getName() + "," + fcTank.getPmapname() + "," + fcTank.getPcoorY()
                                + "," + fcTank.getPcoorY() + "," + fcTank.getPdir() + "," + fcTank.getPactionNum());
                    }
                    String bs = gson.toJson(datas);
                    FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(s));
                    if (fcMutilPlaySender != null) {
                        fcMutilPlaySender.throughTransmissionSend(FCRSocketConstant.COMMON_MOVING_YOUR_TANK, bs.getBytes());
                    }
                }
            });
        }
    }

    //物品更换了操作
    public void syncOthterPlayerTankStateAndItems() {
        if (protocolServer == null) {
            return;
        }
        ArrayList<FCTank> filters = new ArrayList<>();
        //STEP 1判断队伍里是不是有其他玩家的车
        FCPlayerInfo checkPlayer = player1;
        for (int i = -1; i < FCMutilPlayCache.getTeamMembers().size(); i++) {
            if (i == -1) {
            } else {
                FCRPlayerLink link = FCMutilPlayCache.getTeamMembers().get(i);
                checkPlayer = FCMutilPlayCache.findPlayerByName(link.curPlayerHostUID, link.curPlayerName);
            }
            if (checkPlayer != null && checkPlayer.getAliasUID().equals(gameSave.HOST_UID)) {
                if (checkPlayer.getPlayertank1() != null && !checkPlayer.getPlayertank1().equals("null")) {
                    if (!checkPlayer.getPlayertankHostId().equals(gameSave.HOST_UID)) {
                        FCTank fcTank = tankLib.getTankOfID(checkPlayer.getPlayertank1(), checkPlayer.getPlayertankHostId());
                        if (fcTank != null) {
                            filters.add(fcTank);
                        }
                    }
                }
            }
        }
        for (FCTank fcTank : filters) {
            sendTankStateToTargetHost(fcTank.getName(), fcTank.getHostId(), fcTank.getHostId());
        }
    }

    private void sendTankStateToTargetHost(String tankId, String tankHostId, String targetHost) {
        FCTank fcTank = tankLib.getTankOfID(tankId, tankHostId);
        if (fcTank == null) {
            return;
        }
        BigTankPack bigTankPack = new BigTankPack();
        bigTankPack.tank = fcTank;
        FCItem item = null;
        item = FCRMaster.itemLib.getItemOfID(fcTank.getChassisID());
        if (item != null) {
            bigTankPack.tankItems.put(fcTank.getChassisID(), item);
        }
        item = FCRMaster.itemLib.getItemOfID(fcTank.getGunID());
        if (item != null) {
            bigTankPack.tankItems.put(fcTank.getGunID(), item);
        }
        item = FCRMaster.itemLib.getItemOfID(fcTank.getGun2ID());
        if (item != null) {
            bigTankPack.tankItems.put(fcTank.getGun2ID(), item);
        }
        item = FCRMaster.itemLib.getItemOfID(fcTank.getSEID());
        if (item != null) {
            bigTankPack.tankItems.put(fcTank.getSEID(), item);
        }
        item = FCRMaster.itemLib.getItemOfID(fcTank.getEngineID());
        if (item != null) {
            bigTankPack.tankItems.put(fcTank.getEngineID(), item);
        }
        item = FCRMaster.itemLib.getItemOfID(fcTank.getRadarID());
        if (item != null) {
            bigTankPack.tankItems.put(fcTank.getRadarID(), item);
        }
        item = FCRMaster.itemLib.getItemOfID(fcTank.getCdeviceID());
        if (item != null) {
            bigTankPack.tankItems.put(fcTank.getCdeviceID(), item);
        }
        for (String k : fcTank.getKnapsack()) {
            if (k != null && k.contains(",")) {
                item = FCRMaster.itemLib.getItemOfID(k);
                if (item != null) {
                    bigTankPack.tankItems.put(k, item);
                }
            }
        }
        String bigData = gson.toJson(bigTankPack);
        // System.out.println(bigData);
        String compressData = FCMixUtil.compress(bigData);
        // System.out.println(compressData);
        String outData = targetHost + "," + compressData;
        FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(targetHost));
        if (fcMutilPlaySender != null) {
            fcMutilPlaySender.throughTransmissionSend(FCRSocketConstant.COMMON_SYNC_TANK_STATE_ITEMS, outData.getBytes());
        }
    }

    /**
     * 驾驶操作别的玩家的坦克的区域
     **/

    @Override
    public void checkAction(String key, int cmd, long receiveTime,byte... params) {
        SLog.getInstance().e_s(receiveTime+"[TIME] Server ==>" + cmd + "  key=" + key);
        switch (cmd) {
            case FCRSocketConstant.C2S_REQUEST_CHECK_HOSTID:
                String newHostid = new String(params);
                FCPlayerInfo findOne = FCMutilPlayCache.findPlayerByHostId(newHostid);
                byte[] reByte = new byte[1];
                if (findOne == null) {
                    if (!hostIdAndSocketKeyMap.containsKey(newHostid)) {
                        hostIdAndSocketKeyMap.put(newHostid, key);
                    }
                    reByte[0] = 1;//成功了
                } else {
                    reByte[0] = 0;//叫重新改了hostId再来
                }
                FCMutilPlaySender fcMutilPlaySender = senderHelpMaps.get(key);
                fcMutilPlaySender.throughTransmissionSend(FCRSocketConstant.S2C_REPOSNE_CHECK_HOSTID, reByte);
                break;
            case FCRSocketConstant.C2S_REQUEST_JOIN_SERVER:
                sendPlayer(key);
                String data = new String(params);
                ArrayList<FCPlayerInfo> fcPlayerInfos = gson.fromJson(data, new TypeToken<ArrayList<FCPlayerInfo>>() {
                }.getType());
                for (FCPlayerInfo info : fcPlayerInfos) {
                    if (!info.getAliasUID().equals(gameSave.HOST_UID)) {
                        FCMutilPlayCache.joinGame(info);
                    }
                }

                //TODO 还要将共享显示的镜像也全部同步
                syncAllFCPropulsionToClient();
                String compress = FCMixUtil.compress(data);
                byte[] compressB = compress.getBytes();
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.S2C_SEND_RES_PLAYER, compressB);
                    }
                }, key);
                break;
            case FCRSocketConstant.C2S_SEND_MOVING:
                //收到玩家的移动，则要把这个移动信息同步给非这个玩家的人
                FCMutilPlayCache.updateMoving(receiveTime, params);
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.S2C_SEND_MOVING, params);
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_SEND_JOIN:
                byte[] COMMON_SEND_JOINb = new byte[params.length - 1];
                System.arraycopy(params, 1, COMMON_SEND_JOINb, 0, COMMON_SEND_JOINb.length);
                String COMMON_SEND_JOINd = new String(COMMON_SEND_JOINb);
                String[] COMMON_SEND_JOINs = COMMON_SEND_JOINd.split("@");
                if (COMMON_SEND_JOINs[1].equals(gameSave.HOST_UID)) {
                    FCMutilPlayCache.updateJoinInTeam(params, COMMON_SEND_JOINs);
                    //TODO 入队了，主动触发通知一次，当前队伍角色的位置等
                    playerMoving();
                } else {
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(COMMON_SEND_JOINs[1]));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_JOIN, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_SEND_REQUEST_JOIN:
                byte[] COMMON_SEND_REQUEST_JOINd = new byte[params.length - 1];
                System.arraycopy(params, 1, COMMON_SEND_REQUEST_JOINd, 0, COMMON_SEND_REQUEST_JOINd.length);
                String[] COMMON_SEND_REQUEST_JOINs = (new String(COMMON_SEND_REQUEST_JOINd)).split("@");
                if (COMMON_SEND_REQUEST_JOINs[1].equals(gameSave.HOST_UID)) {
                    //   FCMutilPlayCache.getRequestTeam(params, COMMON_SEND_REQUEST_JOINs);
                    //TODO 服务器测试版本阶段拒绝和人组队
                    String fromToData = gameSave.HOST_UID + "@" + COMMON_SEND_REQUEST_JOINs[0];
                    byte[] fromToDatab = fromToData.getBytes();
                    byte[] bytes = new byte[2 + fromToDatab.length];
                    int flag = params[0] & 0xFF;
                    bytes[0] = 0;
                    bytes[1] = (byte) (flag & 0xFF);
                    System.arraycopy(fromToDatab, 0, bytes, 2, fromToDatab.length);
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(COMMON_SEND_REQUEST_JOINs[0]));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_REPO, bytes);
                    }
                } else {
                    //发给别人的
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(COMMON_SEND_REQUEST_JOINs[1]));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_REQUEST_JOIN, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_REPO:
                byte[] COMMON_SEND_REQUEST_JOIN_REPOd = new byte[params.length - 2];
                System.arraycopy(params, 2, COMMON_SEND_REQUEST_JOIN_REPOd, 0, COMMON_SEND_REQUEST_JOIN_REPOd.length);
                String[] COMMON_SEND_REQUEST_JOIN_REPOds = (new String(COMMON_SEND_REQUEST_JOIN_REPOd)).split("@");
                if (COMMON_SEND_REQUEST_JOIN_REPOds[1].equals(gameSave.HOST_UID)) {
                    FCMutilPlayCache.getRequestTeamRepo(params, COMMON_SEND_REQUEST_JOIN_REPOds);
                } else {
                    //发给别人的
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(COMMON_SEND_REQUEST_JOIN_REPOds[1]));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_REPO, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_OUT:
                byte[] COMMON_SEND_REQUEST_JOIN_OUTd = new byte[params.length - 1];
                System.arraycopy(params, 1, COMMON_SEND_REQUEST_JOIN_OUTd, 0, COMMON_SEND_REQUEST_JOIN_OUTd.length);
                String[] COMMON_SEND_REQUEST_JOIN_OUTs = (new String(COMMON_SEND_REQUEST_JOIN_OUTd)).split("@");
                if (COMMON_SEND_REQUEST_JOIN_OUTs[1].equals(gameSave.HOST_UID)) {
                    FCMutilPlayCache.getTeamJoinOut(params, COMMON_SEND_REQUEST_JOIN_OUTs);
                } else {
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(COMMON_SEND_REQUEST_JOIN_OUTs[1]));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_REQUEST_JOIN_OUT, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_SEND_JUMP_EVENT:
                String[] COMMON_SEND_JUMP_EVENTs = (new String(params)).split("@");
                String newEventd = COMMON_SEND_JUMP_EVENTs[0] + "@" + COMMON_SEND_JUMP_EVENTs[1];
                for (int i = 3; i < COMMON_SEND_JUMP_EVENTs.length; i++) {
                    if (COMMON_SEND_JUMP_EVENTs[i].equals(gameSave.HOST_UID)) {
                        //服务机也是队友
                        FCMutilPlayCache.parseJumpEvent(params);
                    } else {
                        FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(COMMON_SEND_JUMP_EVENTs[i]));
                        if (sender != null) {
                            sender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_JUMP_EVENT, newEventd.getBytes());
                        }
                    }
                }
                break;
            case FCRSocketConstant.COMMON_SEND_RES_TANKIOS:
                synchronized (tankLock) {
                    String COMMON_SEND_RES_TANKIOSs = new String(params);
                    String uncompressTanks = FCMixUtil.uncompress(COMMON_SEND_RES_TANKIOSs);
                    ArrayList<FCTank> ds = gson.fromJson(uncompressTanks, new TypeToken<ArrayList<FCTank>>() {
                    }.getType());
                    for (FCTank ios : ds) {
                        FCMutilPlayTankCache.updateAndAddTank(ios);
                    }
                }
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SEND_RES_TANKIOS, params);
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_BATTLE_JUMP:
                //step 1跳转战斗界面
                FCBattlePack pack = gson.fromJson(new String(params), new TypeToken<FCBattlePack>() {
                }.getType());
                for (String targetHost : pack.targetHostIds) {
                    if (targetHost.equals(gameSave.HOST_UID)) {
                        FCMutilPlayCache.parseBattleStart(pack);
                    } else {
                        FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(targetHost));
                        if (sender != null) {
                            sender.throughTransmissionSend(FCRSocketConstant.COMMON_BATTLE_JUMP, params);
                        }
                    }
                }
                break;
            case FCRSocketConstant.COMMON_BATTLE_WRAP_SYNC:
                FCPlayerBattleWrap wrap = gson.fromJson(new String(params), FCPlayerBattleWrap.class);
                for (String targetHost : wrap.targetHostId) {
                    if (targetHost.equals(gameSave.HOST_UID)) {
                        FCMutilPlayCache.updateBattleWrap(wrap);
                    } else {
                        FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(targetHost));
                        if (sender != null) {
                            sender.throughTransmissionSend(FCRSocketConstant.COMMON_BATTLE_WRAP_SYNC, params);
                        }
                    }
                }
                break;
            case FCRSocketConstant.COMMON_BATTLE_RANDOMS:
                RandomPack randomPack = gson.fromJson(new String(params), RandomPack.class);
                for (String targetHost : randomPack.hostids) {
                    if (targetHost.equals(gameSave.HOST_UID)) {
                        FCMutilPlayCache.updateBattleRandoms(randomPack);
                    } else {
                        FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(targetHost));
                        if (sender != null) {
                            sender.throughTransmissionSend(FCRSocketConstant.COMMON_BATTLE_RANDOMS, params);
                        }
                    }
                }
                break;
            case FCRSocketConstant.COMMON_SYNC_EQUIP:
                HashMap<String, String> map = gson.fromJson(new String(params), new TypeToken<HashMap<String, String>>() {
                }.getType());
                FCMutilPlayCache.parseSyncEquip(receiveTime, map);
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SYNC_EQUIP, params);
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_SYNC_FCPropulsion:
                synchronized (tankLock) {
                    FCMutilPlayPropulsionCache.fromNetShareIt(params, false);
                }
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SYNC_FCPropulsion, params);
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_SYNC_UPDOWN_TANK:
                FCMutilPlayCache.parsePlayerUpDownTank(receiveTime, params);
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SYNC_UPDOWN_TANK, params);
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_JOIN_TEAM_FCPropulsion:
                int len = ByteUtil.getInt(new byte[]{params[0], params[1], params[2], params[3]});
                byte[] bytes2 = new byte[params.length - 4 - len];
                System.arraycopy(params, 4 + len, bytes2, 0, bytes2.length);
                byte[] targetHostb = new byte[len];
                System.arraycopy(params, 4, targetHostb, 0, len);
                String targetHostId = new String(targetHostb);
                if (targetHostId.equals(gameSave.HOST_UID)) {
                    //这个指令是专门发给队长的，能收到，证明就是队长，不需要给其他人发
                    FCMutilPlayPropulsionCache.fromNetShareIt(bytes2, true);
                } else {
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(targetHostId));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_JOIN_TEAM_FCPropulsion, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_TEAM_SCREEN_SYNC:
                FCMultiSyncScreenPack fcMultiSyncScreenPack = gson.fromJson(new String(params), FCMultiSyncScreenPack.class);
                FCMutilPlayCache.parseSyncTeamScreen(fcMultiSyncScreenPack);
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        if (sender != null) {
                            sender.throughTransmissionSend(FCRSocketConstant.COMMON_TEAM_SCREEN_SYNC, params);
                        }
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_CHANGE_PLAYER_LIMIT:
                ArrayList<FCPlayerTransport> list = gson.fromJson(new String(params), new TypeToken<ArrayList<FCPlayerTransport>>() {
                }.getType());
                FCMutilPlayCache.parsePlayerSyncState(receiveTime, list);
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_CHANGE_PLAYER_LIMIT, params);
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_UP_DOWN_YOUR_TANK:
                FCMutilPlayCache.parseRemoteUpDownMyTank(params);
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_UP_DOWN_YOUR_TANK, params);
                    }
                }, key);
                break;
            case FCRSocketConstant.COMMON_MOVING_YOUR_TANK:
                ArrayList<String> moveData = gson.fromJson(new String(params), new TypeToken<ArrayList<String>>() {
                }.getType());
                String targetH = moveData.get(0).split(",")[0];
                if (targetH.equals(gameSave.HOST_UID)) {
                    FCMutilPlayCache.parseRemoteMoveTank(receiveTime, moveData);
                } else {
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(targetH));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_MOVING_YOUR_TANK, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_SYNC_TANK_STATE_ITEMS:
                String bigData = new String(params);
                String[] COMMON_SYNC_TANK_STATE_ITEMSsp = bigData.split(",");
                if (COMMON_SYNC_TANK_STATE_ITEMSsp[0].equals(gameSave.HOST_UID)) {
                    String unCompress = FCMixUtil.uncompress(COMMON_SYNC_TANK_STATE_ITEMSsp[1]);
                    BigTankPack bigTankPack = gson.fromJson(unCompress, BigTankPack.class);
                    FCMutilPlayCache.paraseRemoteTankItems(bigTankPack);
                } else {
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(COMMON_SYNC_TANK_STATE_ITEMSsp[0]));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_SYNC_TANK_STATE_ITEMS, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_GIVE_ME_YOUR_TANKITEMS:
                //tankHostId+","+tankId+","+gameSave.HOST_UID;
                String COMMON_GIVE_ME_YOUR_TANKITEMSs = new String(params);
                String[] sp = COMMON_GIVE_ME_YOUR_TANKITEMSs.split(",");
                if (sp[0].equals(gameSave.HOST_UID)) {
                    sendTankStateToTargetHost(sp[1], sp[0], sp[2]);
                } else {
                    FCMutilPlaySender sender = senderHelpMaps.get(hostIdAndSocketKeyMap.get(sp[0]));
                    if (sender != null) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_GIVE_ME_YOUR_TANKITEMS, params);
                    }
                }
                break;
            case FCRSocketConstant.COMMON_PLAYER_TALK_MSG:
                FCMutilPlayCache.parseGetPlayerMsg(gson.fromJson(new String(params), MsgPack.class));
                eachSenderDoExcept(new Work() {
                    @Override
                    public void doWhat(FCMutilPlaySender sender) {
                        sender.throughTransmissionSend(FCRSocketConstant.COMMON_PLAYER_TALK_MSG, params);
                    }
                }, key);
                break;
            default:
                break;
        }
    }
}
